{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# High-level RNN TF Example"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import os\n",
    "import sys\n",
    "import tensorflow as tf\n",
    "from common.params_lstm import *\n",
    "from common.utils import *"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "OS:  linux\n",
      "Python:  3.5.2 |Anaconda custom (64-bit)| (default, Jul  2 2016, 17:53:06) \n",
      "[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)]\n",
      "Numpy:  1.13.3\n",
      "Tensorflow:  1.4.0\n",
      "GPU:  ['Tesla K80']\n"
     ]
    }
   ],
   "source": [
    "print(\"OS: \", sys.platform)\n",
    "print(\"Python: \", sys.version)\n",
    "print(\"Numpy: \", np.__version__)\n",
    "print(\"Tensorflow: \", tf.__version__)\n",
    "print(\"GPU: \", get_gpu_name())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "def create_symbol(CUDNN=True):\n",
    "    word_vectors = tf.contrib.layers.embed_sequence(X, vocab_size=MAXFEATURES, embed_dim=EMBEDSIZE)\n",
    "    word_list = tf.unstack(word_vectors, axis=1)\n",
    "    \n",
    "    if not CUDNN:\n",
    "        cell = tf.contrib.rnn.GRUCell(NUMHIDDEN)\n",
    "        outputs, states = tf.contrib.rnn.static_rnn(cell, word_list, dtype=tf.float32)\n",
    "    else:\n",
    "        # Using cuDNN since vanilla RNN\n",
    "        cudnn_cell = tf.contrib.cudnn_rnn.CudnnGRU(num_layers=1, \n",
    "                                                   num_units=NUMHIDDEN, \n",
    "                                                   input_size=EMBEDSIZE)\n",
    "        params_size_t = cudnn_cell.params_size()\n",
    "        params = tf.Variable(tf.random_uniform([params_size_t], -0.1, 0.1), validate_shape=False)   \n",
    "        input_h = tf.Variable(tf.zeros([1, BATCHSIZE, NUMHIDDEN]))\n",
    "        outputs, states = cudnn_cell(input_data=word_list,\n",
    "                                     input_h=input_h,\n",
    "                                     params=params)\n",
    "        logits = tf.layers.dense(outputs[-1], 2, activation=None, name='output')\n",
    "    return logits"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "def init_model(m):\n",
    "    # Single-class labels, don't need dense one-hot\n",
    "    # Expects unscaled logits, not output of tf.nn.softmax\n",
    "    xentropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=m, labels=y)\n",
    "    loss = tf.reduce_mean(xentropy)\n",
    "    optimizer = tf.train.AdamOptimizer(LR, BETA_1, BETA_2, EPS)\n",
    "    training_op = optimizer.minimize(loss)\n",
    "    return training_op"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Preparing train set...\n",
      "Preparing test set...\n",
      "Trimming to 30000 max-features\n",
      "Padding to length 150\n",
      "(25000, 150) (25000, 150) (25000,) (25000,)\n",
      "int32 int32 int32 int32\n",
      "CPU times: user 5.99 s, sys: 250 ms, total: 6.24 s\n",
      "Wall time: 6.24 s\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "# Data into format for library\n",
    "x_train, x_test, y_train, y_test = imdb_for_library(seq_len=MAXLEN, max_features=MAXFEATURES)\n",
    "print(x_train.shape, x_test.shape, y_train.shape, y_test.shape)\n",
    "print(x_train.dtype, x_test.dtype, y_train.dtype, y_test.dtype)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 1.43 s, sys: 119 ms, total: 1.55 s\n",
      "Wall time: 11.4 s\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "# Place-holders\n",
    "X = tf.placeholder(tf.int32, shape=[None, MAXLEN])\n",
    "y = tf.placeholder(tf.int32, shape=[None])\n",
    "sym = create_symbol()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 1.01 s, sys: 457 ms, total: 1.47 s\n",
      "Wall time: 1.51 s\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "model = init_model(sym)\n",
    "init = tf.global_variables_initializer()\n",
    "sess = tf.Session()\n",
    "sess.run(init)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 Train accuracy: 0.875\n",
      "1 Train accuracy: 0.90625\n",
      "2 Train accuracy: 0.984375\n",
      "CPU times: user 24.1 s, sys: 2.75 s, total: 26.9 s\n",
      "Wall time: 29.8 s\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "# 30s\n",
    "# Accuracy logging\n",
    "correct = tf.nn.in_top_k(sym, y, 1)\n",
    "accuracy = tf.reduce_mean(tf.cast(correct, tf.float32))\n",
    "\n",
    "for j in range(EPOCHS):\n",
    "    for data, label in yield_mb(x_train, y_train, BATCHSIZE, shuffle=True):\n",
    "        sess.run(model, feed_dict={X: data, y: label})\n",
    "    # Log\n",
    "    acc_train = sess.run(accuracy, feed_dict={X: data, y: label})\n",
    "    print(j, \"Train accuracy:\", acc_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 10.9 s, sys: 2.18 s, total: 13.1 s\n",
      "Wall time: 12.8 s\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "n_samples = (y_test.shape[0]//BATCHSIZE)*BATCHSIZE\n",
    "y_guess = np.zeros(n_samples, dtype=np.int)\n",
    "y_truth = y_test[:n_samples]\n",
    "c = 0\n",
    "for data, label in yield_mb(x_test, y_test, BATCHSIZE):\n",
    "    pred = tf.argmax(sym, 1)\n",
    "    output = sess.run(pred, feed_dict={X: data})\n",
    "    y_guess[c*BATCHSIZE:(c+1)*BATCHSIZE] = output\n",
    "    c += 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy:  0.861378205128\n"
     ]
    }
   ],
   "source": [
    "print(\"Accuracy: \", sum(y_guess == y_truth)/len(y_guess))"
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python [default]",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
